"""
视频合成API蓝图
提供视频合成功能，包括文件上传、遮罩应用、字幕添加、音频合成和背景音乐添加
"""

from flask import Blueprint, request, jsonify, send_file, current_app
import os
import logging
import json
import uuid
import shutil
from app.service.video_service import VideoService
from app.service.subtitle_service import SubtitleService
from app.tools.utils import get_safe_filename, validate_file_extension

# 创建视频合成API蓝图
merge_bp = Blueprint('merge', __name__, url_prefix='/merge')

def allowed_file(filename, allowed_extensions):
    """检查文件格式是否允许"""
    return validate_file_extension(filename, allowed_extensions)

def get_video_service():
    """获取视频服务实例"""
    return VideoService(current_app.config['UPLOAD_FOLDER'], current_app.config['OUTPUT_FOLDER'])

def get_subtitle_service():
    """获取字幕服务实例"""
    return SubtitleService(current_app.config['UPLOAD_FOLDER'], current_app.config['OUTPUT_FOLDER'])

def create_merge_temp_folder(folder_name):
    """创建合并临时文件夹"""
    temp_base = os.path.join(current_app.config['UPLOAD_FOLDER'], 'merge_temp')
    if not os.path.exists(temp_base):
        os.makedirs(temp_base)
    
    merge_folder = os.path.join(temp_base, folder_name)
    if not os.path.exists(merge_folder):
        os.makedirs(merge_folder)
    
    return merge_folder

def cleanup_merge_folder(folder_path):
    """清理合并文件夹"""
    try:
        if os.path.exists(folder_path):
            shutil.rmtree(folder_path)
    except Exception as e:
        logging.warning(f"清理合并文件夹失败: {e}")

@merge_bp.route('/upload_file', methods=['POST'])
def upload_file():
    """上传文件到合并临时文件夹"""
    try:
        # 检查必要参数
        folder_name = request.form.get('folder_name')
        file_type = request.form.get('file_type')
        
        if not folder_name:
            return jsonify({'error': '缺少文件夹名称参数'}), 400
        
        if not file_type:
            return jsonify({'error': '缺少文件类型参数'}), 400
        
        if file_type not in ['subtitle', 'audio', 'video', 'background_music']:
            return jsonify({'error': '文件类型必须是 subtitle、audio、video 或 background_music'}), 400
        
        # 检查是否有文件上传
        if 'file' not in request.files:
            return jsonify({'error': '没有上传文件'}), 400
        
        file = request.files['file']
        if file.filename == '':
            return jsonify({'error': '没有选择文件'}), 400
        
        # 根据文件类型检查格式
        if file_type == 'video':
            if not allowed_file(file.filename, ['mp4','webm','mov','avi','mkv','flv','wmv']):
                return jsonify({'error': '不支持的视频文件格式'}), 400
        elif file_type == 'audio':
            if not allowed_file(file.filename,['mp3','wav']):
                return jsonify({'error': '不支持的音频文件格式'}), 400
        elif file_type == 'subtitle':
            if not allowed_file(file.filename, ['srt', 'vtt', 'ass']):
                return jsonify({'error': '不支持的字幕文件格式'}), 400
        elif file_type == 'background_music':
            if not allowed_file(file.filename,['mp3','wav']):
                return jsonify({'error': '不支持的背景音乐文件格式'}), 400
        
        # 创建临时文件夹
        merge_folder = create_merge_temp_folder(folder_name)
        
        # 根据文件类型确定目标文件名
        if file_type == 'subtitle':
            target_filename = 'subtitle.srt'
        elif file_type == 'audio':
            target_filename = 'audio.mp3'
        elif file_type == 'video':
            target_filename = 'source.mp4'
        elif file_type == 'background_music':
            target_filename = 'background_music.mp3'
        
        # 保存文件
        target_path = os.path.join(merge_folder, target_filename)
        file.save(target_path)
        
        return jsonify({
            'success': True,
            'message': f'{file_type}文件上传成功',
            'folder_name': folder_name,
            'file_type': file_type,
            'target_path': target_path
        })
    
    except Exception as e:
        logging.error(f"文件上传失败: {e}")
        return jsonify({'error': str(e)}), 500

@merge_bp.route('/apply_mask', methods=['POST'])
def apply_mask_to_video():
    """在视频区域下绘制遮罩"""
    try:
        # 检查必要参数
        folder_name = request.form.get('folder_name')
        mask_data = request.form.get('mask_data')
        video_file = request.form.get('video_file')
        
        if not folder_name:
            return jsonify({'error': '缺少文件夹名称参数'}), 400
        
        if not mask_data:
            return jsonify({'error': '没有提供遮挡数据'}), 400
        
        try:
            mask_info = json.loads(mask_data)
        except json.JSONDecodeError:
            return jsonify({'error': '遮挡数据格式错误'}), 400
        
        # 构建临时文件夹路径
        temp_base = os.path.join(current_app.config['UPLOAD_FOLDER'], 'merge_temp')
        merge_folder = os.path.join(temp_base, folder_name)
        
        if not video_file:
            return jsonify({'error': '缺少视频文件参数'}), 400
        
        source_video_path = os.path.join(merge_folder, video_file)
        
        # 检查源视频文件是否存在
        if not os.path.exists(source_video_path):
            return jsonify({'error': '源视频文件不存在，请先上传视频文件'}), 400
        
        # 应用遮罩
        video_service = get_video_service()
        result = video_service.apply_mask_service(source_video_path, mask_info, False, 0, None)
        
        if not result['success']:
            return jsonify({'error': result['error']}), 500
        
        # 将处理后的视频复制到临时文件夹
        masked_video_path = os.path.join(merge_folder, 'masked_video.mp4')
        shutil.copy2(result['output_path'], masked_video_path)
        
        # 清理临时输出文件
        try:
            os.remove(result['output_path'])
        except:
            pass
        
        return jsonify({
            'success': True,
            'message': '遮罩应用成功',
            'masked_video_path': masked_video_path
        })
    
    except Exception as e:
        logging.error(f"应用遮罩失败: {e}")
        return jsonify({'error': str(e)}), 500

@merge_bp.route('/add_subtitle', methods=['POST'])
def add_subtitle_to_video():
    """在视频中添加字幕"""
    try:
        # 检查必要参数
        folder_name = request.form.get('folder_name')
        subtitle_data = request.form.get('subtitle_data', '{}')
        video_file = request.form.get('video_file')
        subtitle_file = request.form.get('subtitle_file')
        
        if not folder_name:
            return jsonify({'error': '缺少文件夹名称参数'}), 400
        
        # 构建临时文件夹路径
        temp_base = os.path.join(current_app.config['UPLOAD_FOLDER'], 'merge_temp')
        merge_folder = os.path.join(temp_base, folder_name)
        
        # 确定输入视频文件路径
        if not video_file:
            return jsonify({'error': '缺少视频文件参数'}), 400
        
        source_video_path = os.path.join(merge_folder, video_file)
        
        # 优先使用遮罩处理后的视频，如果没有则使用原始视频
        if os.path.exists(source_video_path):
            input_video_path = source_video_path
        else:
            return jsonify({'error': '视频文件不存在，请先上传视频文件'}), 400
        
        # 检查字幕文件是否存在
        if not subtitle_file:
            return jsonify({'error': '缺少字幕文件参数'}), 400
        
        subtitle_path = os.path.join(merge_folder, subtitle_file)
        if not os.path.exists(subtitle_path):
            return jsonify({'error': '字幕文件不存在，请先上传字幕文件'}), 400
        
        # 解析字幕设置
        try:
            subtitle_settings = json.loads(subtitle_data)
        except json.JSONDecodeError:
            subtitle_settings = {}
        
        # 添加字幕
        subtitle_service = get_subtitle_service()
        result = subtitle_service.apply_subtitle_service(input_video_path, subtitle_path, subtitle_settings)
        
        if not result['success']:
            return jsonify({'error': result['error']}), 500
        
        # 将处理后的视频复制到临时文件夹
        subtitled_video_path = os.path.join(merge_folder, 'subtitled_video.mp4')
        shutil.copy2(result['output_path'], subtitled_video_path)
        
        # 清理临时输出文件
        try:
            os.remove(result['output_path'])
        except:
            pass
        
        return jsonify({
            'success': True,
            'message': '字幕添加成功',
            'subtitled_video_path': subtitled_video_path
        })
    
    except Exception as e:
        logging.error(f"添加字幕失败: {e}")
        return jsonify({'error': str(e)}), 500

@merge_bp.route('/merge_audio', methods=['POST'])
def merge_audio_with_video():
    """合成语音"""
    try:
        # 检查必要参数
        folder_name = request.form.get('folder_name')
        merge_type = request.form.get('merge_type', 'mix')
        original_volume = float(request.form.get('original_volume', 1.0))
        new_audio_volume = float(request.form.get('new_audio_volume', 1.0))
        fade_in_duration = float(request.form.get('fade_in_duration', 0))
        fade_out_duration = float(request.form.get('fade_out_duration', 0))
        
        if not folder_name:
            return jsonify({'error': '缺少文件夹名称参数'}), 400
        
        # 构建临时文件夹路径
        temp_base = os.path.join(current_app.config['UPLOAD_FOLDER'], 'merge_temp')
        merge_folder = os.path.join(temp_base, folder_name)
        
        # 确定输入视频文件路径
        video_file = request.form.get('video_file')
        if not video_file:
            return jsonify({'error': '缺少视频文件参数'}), 400
        
        source_video_path = os.path.join(merge_folder, video_file)
        
        # 按优先级选择输入视频
        if os.path.exists(source_video_path):
            input_video_path = source_video_path
        else:
            return jsonify({'error': '视频文件不存在，请先上传视频文件'}), 400
        
        # 检查音频文件是否存在
        audio_file = request.form.get('audio_file')
        if not audio_file:
            return jsonify({'error': '缺少音频文件参数'}), 400
        
        audio_path = os.path.join(merge_folder, audio_file)
        if not os.path.exists(audio_path):
            return jsonify({'error': '音频文件不存在，请先上传音频文件'}), 400
        
        # 合并音频
        video_service = get_video_service()
        result = video_service.merge_video_audio_service(
            input_video_path, audio_path, merge_type, original_volume,
            new_audio_volume, fade_in_duration, fade_out_duration
        )
        
        if not result['success']:
            return jsonify({'error': result['error']}), 500
        
        # 将处理后的视频复制到临时文件夹
        merged_audio_video_path = os.path.join(merge_folder, 'merged_audio_video.mp4')
        shutil.copy2(result['output_path'], merged_audio_video_path)
        
        # 清理临时输出文件
        try:
            os.remove(result['output_path'])
        except:
            pass
        
        return jsonify({
            'success': True,
            'message': '音频合成成功',
            'merged_audio_video_path': merged_audio_video_path
        })
    
    except Exception as e:
        logging.error(f"音频合成失败: {e}")
        return jsonify({'error': str(e)}), 500

@merge_bp.route('/add_background_music', methods=['POST'])
def add_background_music_to_video():
    """添加背景音乐"""
    try:
        # 检查必要参数
        folder_name = request.form.get('folder_name')
        volume_ratio = float(request.form.get('volume_ratio', 0.3))
        loop_music = request.form.get('loop_music', 'true').lower() == 'true'
        fade_in_duration = float(request.form.get('fade_in_duration', 0))
        fade_out_duration = float(request.form.get('fade_out_duration', 0))
        start_time = float(request.form.get('start_time', 0))
        end_time = request.form.get('end_time')
        if end_time:
            end_time = float(end_time)
        
        if not folder_name:
            return jsonify({'error': '缺少文件夹名称参数'}), 400
        
        # 构建临时文件夹路径
        temp_base = os.path.join(current_app.config['UPLOAD_FOLDER'], 'merge_temp')
        merge_folder = os.path.join(temp_base, folder_name)
        
        # 确定输入视频文件路径
        video_file = request.form.get('video_file')
        if not video_file:
            return jsonify({'error': '缺少视频文件参数'}), 400
        
        source_video_path = os.path.join(merge_folder, video_file)
        
        # 按优先级选择输入视频
        if os.path.exists(source_video_path):
            input_video_path = source_video_path
        else:
            return jsonify({'error': '视频文件不存在，请先上传视频文件'}), 400
        
        # 检查音频文件是否存在
        bgm_file = request.form.get('bgm_file')
        if not bgm_file:
            return jsonify({'error': '缺少背景音乐文件参数'}), 400
        
        audio_path = os.path.join(merge_folder, bgm_file)
        if not os.path.exists(audio_path):
            return jsonify({'error': '音频文件不存在，请先上传音频文件'}), 400
        
        # 添加背景音乐
        video_service = get_video_service()
        result = video_service.add_background_music_with_options_service(
            input_video_path, audio_path, volume_ratio, loop_music,
            fade_in_duration, fade_out_duration, start_time, end_time
        )
        
        if not result['success']:
            return jsonify({'error': result['error']}), 500
        
        # 将处理后的视频复制到临时文件夹
        final_video_path = os.path.join(merge_folder, 'final_video.mp4')
        shutil.copy2(result['output_path'], final_video_path)
        
        # 清理临时输出文件
        try:
            os.remove(result['output_path'])
        except:
            pass
        
        return jsonify({
            'success': True,
            'message': '背景音乐添加成功',
            'final_video_path': final_video_path
        })
    
    except Exception as e:
        logging.error(f"添加背景音乐失败: {e}")
        return jsonify({'error': str(e)}), 500

@merge_bp.route('/download_final_video', methods=['GET'])
def download_final_video():
    """下载最终合成的视频文件"""
    try:
        folder_name = request.args.get('folder_name')
        
        if not folder_name:
            return jsonify({'error': '缺少文件夹名称参数'}), 400
        
        # 构建临时文件夹路径
        temp_base = os.path.join(current_app.config['UPLOAD_FOLDER'], 'merge_temp')
        merge_folder = os.path.join(temp_base, folder_name)
        
        # 按优先级查找最终视频文件
        video_file = request.args.get('video_file')
        if not video_file:
            return jsonify({'error': '缺少视频文件参数'}), 400
        
        final_video_path = os.path.join(merge_folder, video_file)
        
        # 确定要下载的文件路径
        if os.path.exists(final_video_path):
            download_path = final_video_path
            download_name = 'final_video.mp4'
        else:
            return jsonify({'error': '没有找到可下载的视频文件'}), 404
        
        return send_file(download_path, as_attachment=True, download_name=download_name)
    
    except Exception as e:
        logging.error(f"下载最终视频失败: {e}")
        return jsonify({'error': str(e)}), 500

@merge_bp.route('/cleanup', methods=['POST'])
def cleanup_merge_folder():
    """清理合并临时文件夹"""
    try:
        folder_name = request.form.get('folder_name')
        
        if not folder_name:
            return jsonify({'error': '缺少文件夹名称参数'}), 400
        
        # 构建临时文件夹路径
        temp_base = os.path.join(current_app.config['UPLOAD_FOLDER'], 'merge_temp')
        merge_folder = os.path.join(temp_base, folder_name)
        
        # 清理文件夹
        cleanup_merge_folder(merge_folder)
        
        return jsonify({
            'success': True,
            'message': '临时文件夹清理成功'
        })
    
    except Exception as e:
        logging.error(f"清理临时文件夹失败: {e}")
        return jsonify({'error': str(e)}), 500 